<template>
  <div class="wh-maptalks-wraper">
    <div class="wh-maptalks" id="wh-map-component-maptalks"></div>
    <div ref="wh-maptalks-infoWindow">
      <div class="wh-maptalks-infoWindow">
        <div class="wh-maptalks-infoWindow-title">
          <p>
            {{currentInfo.title || '提示'}}
          </p>
          <img @click="onCloseInfoWindow" src="../assets/close.png" alt="">
        </div>
        <div class="wh-maptalks-infoWindow-content">
          {{currentInfo.content || '内容'}}
        </div>
        <div class="wh-maptalks-infoWindow-bottom"></div>
      </div>
    </div>
  </div>
</template>

<script>
import * as maptalks from '../common/maptalks/maptalks.min.js'
import "../common/maptalks/maptalks.css";
// import loadScript from '../common/loadScript.js'
export default {
  props: {

  },
  data() {
    return {
      map: null,
      markerLayer: null,
      polygonLayer: null,
      config: null,
      pathArr: [],
      pathCopyArr: [],
      pathLayer: null,
      pointArr: [],
      infoWindow: null,
      currentInfo: {},
      THREE: null,
      pointMoveArr: [],

    }
  },
  props: {
    loadedMap: {
      type: Function,
      default: null
    },
  },
  mounted() {

  },
  methods: {
    loadMap (options) {
      console.log('创建maptalks地图');
      return new Promise((resolve, reject) => {
        this.map = new maptalks.Map('wh-map-component-maptalks', {
          // https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png
          baseLayer: new maptalks.TileLayer('base', {
            urlTemplate: options.loadConfig.tileUrl?options.loadConfig.tileUrl:'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.jpg',
            subdomains: ['a','b','c', 'd'],
            attribution:  false
          }),
          seamlessZoom: true,
          ...options.mapConfig
        })
        //  设置边界
        if (options.mapConfig.bounds && options.mapConfig.bounds.length === 2) {
          const extent = new maptalks.Extent(new maptalks.Coordinate(options.mapConfig.bounds[0][0], options.mapConfig.bounds[0][1]), new maptalks.Coordinate(options.mapConfig.bounds[1][0], options.mapConfig.bounds[1][1]))
          console.log(extent);
          this.map.setMaxExtent(extent)
        }
        this.map.on('click', this.onClickMap)

        //  标注图层
        this.markerLayer = new maptalks.VectorLayer('marker', {
          enableAltitude : true,
          drawAltitude : {
            lineWidth : 5,
            lineColor : '#0077F1'
          },
          zIndex: 20
        })
        this.markerLayer.addTo(this.map)
        //  多边形图层
        this.polygonLayer = new maptalks.VectorLayer('polygon', {
          enableAltitude : true,
          zIndex: 10
        }).addTo(this.map)

        this.pathLayer = new maptalks.VectorLayer('path', {
          zIndex: 15
        }).addTo(this.map);

        this.initInfoWindow()
        this.loadedMap(this.map)
        resolve(this.map)
      })
    },
    initInfoWindow () {
      this.infoWindow = new maptalks.ui.InfoWindow({
        autoOpenOn: null,
        autoCloseOn: 'click',
        // width: 300,
        custom: true,
        dy: -45,
        zIndex: 30,
        // eventsPropagation: true,
        // eventsToStop: true,
        content: this.$refs['wh-maptalks-infoWindow']
      })
      this.infoWindow.addTo(this.map)
    },
    loadMarker (markerList) {
      console.log('加载 marker');
      var markers = []
      for (var i = 0; i < markerList.length; i++) {
        var markerOptions = markerList[i].options?markerList[i].options:{}
        markerOptions.markerFile = markerOptions.icon || require('../assets/marker/marker-6.png')
        markerOptions.markerWidth = markerOptions.width || 28
        markerOptions.markerHeight = markerOptions.height || 28
        markerOptions.markerOpacity = markerOptions.opacity || 1
        for (var j = 0; j < markerList[i].list.length; j++) {
          var marker = new maptalks.Marker(markerList[i].list[j].position, {
            properties: {
              showInfoWindow: markerOptions.showInfoWindow,
              customInfoWindow: markerOptions.customInfoWindow,
              ...markerList[i].list[j].properties
            },
            symbol: markerOptions,
            zIndex: markerOptions.zIndex || 20
          })
          marker.on('click', this.onClickMarker)
          markers.push(marker)
        }

      }
      this.markerLayer.addGeometry(markers)
    },
    loadPolygon (polygonList) {
      console.log('加载 plygon');
      // visible : polygonList[i].visible || true,
      // editable : polygonList[i].editable ||false,
      // cursor : polygonList[i].cursor || 'pointer',
      // draggable: polygonList[i].draggable || false,
      // dragShadow: polygonList[i].dragShadow || false, // display a shadow during dragging
      // drawOnAxis: polygonList[i].drawOnAxis || null,  // force dragging stick on a axis, can be: x, y
      // symbol: polygonList[i].symbol || {
      //   'lineColor' : '#0000FF',
      //   'lineWidth' : 3,
      //   'polygonFill' : '#0000FF',
      //   'polygonOpacity' : 0.5
      // },
      var polygons = []
      for (var i = 0; i < polygonList.length; i++) {
        var polygonOptions = polygonList[i].options? polygonList[i].options:{}
        polygonOptions.lineColor = polygonOptions.lineColor || '#00D3FC'
        polygonOptions.lineWidth = polygonOptions.lineWidth || 2
        polygonOptions.lineOpacity = polygonOptions.lineOpacity || 1
        polygonOptions.lineDasharray = polygonOptions.lineStyle === 'dashed'?[5]:null
        polygonOptions.polygonFill = polygonOptions.color || '#00D3FC'
        polygonOptions.polygonOpacity = polygonOptions.opacity || 0.5
        var polygon = new maptalks.Polygon([polygonList[i].path], {
          properties: {
            showInfoWindow: polygonOptions.showInfoWindow,
            customInfoWindow: polygonOptions.customInfoWindow,
            ...polygonList[i].properties
          },
          symbol: polygonOptions,
          zIndex: polygonOptions.zIndex || 10
        });
        // polygon.setProperties(polygonList[i].extData)
        polygon.on('click', this.onClickPolygon)
        polygons.push(polygon)
      }
      this.polygonLayer.addGeometry(polygons)
    },
    loadSpecialPath (config) {
    },
    loadPath (config) {
      if (!this.THREE) {
        this.THREE = require('../common/three.module.min.js')
      }

      console.log(' 加载路径');
      // this.pathArr = []
      // this.pathCopyArr = []
      // this.pointArr = []
      this.config = config

      var options = config.options?config.options:{}
      // 起点
      var startSymbol = {
        icon: require('../assets/marker/start.png'),
        width: 28,
        height: 28
      }
      if (options.start && options.start.icon) {
        startSymbol.icon = options.start.icon
      }
      if (options.start && options.start.width) {
        startSymbol.width = options.start.width
      }
      if (options.start && options.start.height) {
        startSymbol.height = options.start.height
      }
      // 终点
      var endSymbol = {
        icon: require('../assets/marker/end.png'),
        width: 28,
        height: 28
      }
      if (options.end && options.end.icon) {
        endSymbol.icon = options.end.icon
      }
      if (options.end && options.end.width) {
        endSymbol.width = options.end.width
      }
      if (options.end && options.end.height) {
        endSymbol.height = options.end.height
      }
      // 图标
      var pointSymbol = {
        icon: require('../assets/marker/car.png'),
        width: 28,
        height: 28
      }
      if (options.point && options.point.icon) {
        pointSymbol.icon = options.point.icon
      }
      if (options.point && options.point.width) {
        pointSymbol.width = options.point.width
      }
      if (options.point && options.point.height) {
        pointSymbol.height = options.point.height
      }
      //  线条样式
      var pathStyle = {
        color: 'red',
        width: 5,
        defaultColor: '#00D3FC',
        speed: 80 // m/s
      }
      if (options.line && options.line.defaultColor) {
        pathStyle.defaultColor = options.line.defaultColor
      }
      if (options.line && options.line.width) {
        pathStyle.width = options.line.width
      }
      if (options.line && options.line.color) {
        pathStyle.color = options.line.color
      }
      if (options.speed) {
        pathStyle.speed = options.speed
      }
      for (var i = 0; i < config.list.length; i++) {
        let startMarker = new maptalks.Marker(config.list[i].path[0], {
          symbol: {
            markerFile: startSymbol.icon,
            markerWidth: startSymbol.width,
            markerHeight: startSymbol.height
          },
          properties: {
            index: i
          },
          zIndex: 20
        }).addTo(this.pathLayer)
        let rotation = this.getPointRotation(config.list[i].path[1], config.list[i].path[0])
        let pointMarker = new maptalks.Marker(config.list[i].path[0], {
          symbol: {
            markerFile: pointSymbol.icon,
            markerWidth: pointSymbol.width,
            markerHeight: pointSymbol.height,
            markerDx: 0,
            markerDy: pointSymbol.height/2,
            // markerPlacement: 'vertex', //vertex, point, vertex-first, vertex-last, center
            // markerVerticalAlignment: 'middle'
            markerRotation: rotation
          },
          properties: {
            index: i
          },
          zIndex: 30
        }).addTo(this.pathLayer)
        pointMarker.on('click', (e) => {
          this.onClickPoint(e, pathStyle)
        })
        this.pointArr.push(pointMarker)
        this.pointMoveArr.push([])
        let endMarker = new maptalks.Marker(config.list[i].path[config.list[i].path.length - 1], {
          symbol: {
            markerFile: endSymbol.icon,
            markerWidth: endSymbol.width,
            markerHeight: endSymbol.height
          },
          zIndex: 20
        }).addTo(this.pathLayer)
        let path = new maptalks.LineString(
          config.list[i].path,
          {
            properties: config.list[i].properties,
            symbol: {
              lineColor: pathStyle.defaultColor,
              lineWidth: pathStyle.width,
              // markerFile: pointSymbol.icon,
              // markerPlacement: 'vertex-first', //vertex, point, vertex-first, vertex-last, center
              // markerVerticalAlignment: 'middle',
              // markerWidth: 30,
              // markerHeight: 30
            }
          }
        ).addTo(this.pathLayer)
        this.pathArr.push(path)

        let pathCopy = path.copy()
        this.pathCopyArr.push(pathCopy)

      }
      if (options.autoMove) {
        this.pointArr.forEach(ele => {
          ele.fire('click', (e) => {
            this.onClickPoint(e, pathStyle)
          })
        })
      }

    },
    onClickPoint (e, pathStyle) {
      if (e.domEvent) {
        e.domEvent.stopPropagation()
      }
      let index = e.target.getProperties().index
      var pathCopy = this.pathCopyArr[index]
      var path = this.pathArr[index]
      let pointMoveArr = this.pointMoveArr[index]
      var point = this.pointArr[index]
      var time = path.getLength() / pathStyle.speed * 1000
      if (pathCopy.getSymbol().lineColor === pathStyle.color) {
        point.setCoordinates(path.getFirstCoordinate())
        pointMoveArr = []
        pathCopy.remove()
      }
      pathCopy.updateSymbol({
        lineColor: pathStyle.color
      })
      pathCopy.addTo(this.pathLayer)
      pathCopy.animateShow({
        duration: time,
        easing: 'linear'
      }, (frame, c) => {
        point.setCoordinates(c)
        pointMoveArr.push([c.x, c.y])
        if (pointMoveArr.length>1) {
          let lastPoint = pointMoveArr[pointMoveArr.length-2]
          point.updateSymbol({
            markerRotation: this.getPointRotation([c.x, c.y], lastPoint)
          })
        }
        if (frame.state.playState === 'finished') {
          const options = this.config.options?this.config.options:{}
          if (options.loop) {
            this.onClickPoint(e, pathStyle)
          }
        }
      });
    },
    onCloseInfoWindow () {
      this.infoWindow.hide();
      this.currentInfo = {}
    },
    getPointRotation (lonlat1, lonlat2) {
      var lon1=this.THREE.MathUtils.degToRad(lonlat1[0])
      var lat1=this.THREE.MathUtils.degToRad(lonlat1[1])
      var lon2=this.THREE.MathUtils.degToRad(lonlat2[0])
      var lat2=this.THREE.MathUtils.degToRad(lonlat2[1])
      if(lon1==lon2){
      	if (lat2 >= lat1){
          return 180
        }else{
          return 0
        }
      }
      if (lat1 == lat2){
        if(lon2 > lon1 ){
          return 90
        }else if(lon2 < lon1){
          return -90
      	}
      }
      var a = this.THREE.MathUtils.radToDeg(Math.atan((lon2 - lon1) * Math.cos(lat2) / (lat2 - lat1)))
      if(lat2 > lat1){
        if(lon2 > lon1){
          return 180 - a
        }else{
          return 180 - (a + 360)
        }
      }else{
        return -a
      }
    },
    onClickMarker (e) {
      this.currentInfo = e.target.getProperties()
      if (this.currentInfo.showInfoWindow) {
        if (this.currentInfo.customInfoWindow) {
          this.infoWindow.setContent(this.currentInfo.customInfoWindow)
        } else {
          this.infoWindow.setContent(this.$refs['wh-maptalks-infoWindow'])
        }
        this.infoWindow.show(e.target.getCoordinates());
      }
      e.domEvent.stopPropagation()
      this.$emit('on-click-marker', e, this.currentInfo, this.infoWindow)
    },
    onClickPolygon (e) {
      this.currentInfo = e.target.getProperties()
      if (this.currentInfo.showInfoWindow) {
        if (this.currentInfo.customInfoWindow) {
          this.infoWindow.setContent(this.currentInfo.customInfoWindow)
        } else {
          this.infoWindow.setContent(this.$refs['wh-maptalks-infoWindow'])
        }
        this.infoWindow.show(e.coordinate);
      }
      e.domEvent.stopPropagation()
      this.$emit('on-click-polygon', e, this.currentInfo, this.infoWindow)
    },
    onClickMap (e) {
      console.log('点击了地图');
      if (this.infoWindow.isVisible()) {
        this.infoWindow.hide()
      }
      this.$emit('on-click-map', e)
    }
  },
}
</script>

<style scoped>
  .wh-maptalks,
  .wh-maptalks-wraper {
    width: 100%;
    height: 100%;
  }
  .wh-maptalks-infoWindow {
    width: 300px;
    background: rgba(39,40,34, 0.8);
    left: -1000px;
    box-sizing: border-box;
    border-radius: 5px;
    overflow: hidden;
  }
  .wh-maptalks-infoWindow-title {
    padding: 10px 16px;
    box-sizing: border-box;
    background: rgba(27,29,25, 0.8);
    color: #dbdbdb;
    font-weight: 500;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
  .wh-maptalks-infoWindow-title>p {
    flex-shrink: 0;
    font-size: 16px;
    margin: 0;
  }
  .wh-maptalks-infoWindow-title>img {
    flex-shrink: 1;
    width: 20px;
    display: block;
    cursor: pointer;
  }
  .wh-maptalks-infoWindow-content {
    padding: 10px 16px;
    box-sizing: border-box;
    color: #dbdbdb;
    text-align: left;
    font-weight: 400;
  }
  .wh-maptalks-infoWindow-bottom {
    position: absolute;
    left: 50%;
    bottom: -40px;
    margin-left: -20px;
    width: 0;
    height: 0;
    border-top: 20px solid rgba(39,40,34, 0.8);
    border-right: 20px solid transparent;
    border-left: 20px solid transparent;
    border-bottom: 20px solid transparent;
  }
  >>> .maptalks-attribution {
    display: none !important;
  }
</style>
